/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * HidSetupForm.java
 *
 * Created on Nov 24, 2009, 11:07:53 PM
 */
package wekinator;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import wekinator.HidSetup.HidState;
import wekinator.util.OverwritePromptingFileChooser;
import wekinator.util.Util;

/**
 *
 * @author rebecca
 */
public class HidSetupForm extends javax.swing.JFrame {

    //TODO: Problem! in any case, global setup should go back to how it was... 
    private HidSetup mySetup = new HidSetup();
    private HidSetup backup = WekinatorInstance.getWekinatorInstance().getCurrentHidSetup();
    private FeatureConfigurationPanel parent = null;

    //  private  setupPropertyListener = null;
    private PropertyChangeListener setupListener = new PropertyChangeListener() {

        public void propertyChange(PropertyChangeEvent evt) {
            setupPropertyChange(evt);
        }
    };
    private boolean inInteractiveSetup = false;
    //  public static final String PROP_MYCURRENTSETUP = "myCurrentSetup";

    /**
     * Get the value of myCurrentSetup
     *
     * @return the value of myCurrentSetup
     */
    public HidSetup getMyCurrentSetup() {
        return mySetup;
    }

    /**
     * Set the value of myCurrentSetup
     *
     * @param myCurrentSetup new value of myCurrentSetup
     */
    protected void setMyCurrentSetup(HidSetup myCurrentSetup) {
        //1st deal with listeners
        HidSetup oldSetup = this.mySetup;
        oldSetup.removePropertyChangeListener(setupListener);
        this.mySetup = myCurrentSetup;
        mySetup.addPropertyChangeListener(setupListener);
    //   propertyChangeSupport.firePropertyChange(PROP_MYCURRENTSETUP, oldSetup, mySetup);
    }
    private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    /**
     * Add PropertyChangeListener.
     *
     * @param listener
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.addPropertyChangeListener(listener);
    }

    /**
     * Remove PropertyChangeListener.
     *
     * @param listener
     */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        propertyChangeSupport.removePropertyChangeListener(listener);
    }

    /** Creates new form HidSetupForm */
    public HidSetupForm() {
        initComponents();
        mySetup.addPropertyChangeListener(setupListener);
    }

    public HidSetupForm(FeatureConfigurationPanel parent) {
        initComponents();
        this.parent = parent;
        mySetup.addPropertyChangeListener(setupListener);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonCancel = new javax.swing.JButton();
        buttonOK = new javax.swing.JButton();
        buttonLoadOtherHID = new javax.swing.JButton();
        buttonIdentifyNewHID = new javax.swing.JButton();
        buttonSaveHidFile = new javax.swing.JButton();
        labelStatus = new javax.swing.JLabel();
        labelDescription = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        buttonCancel.setText("Cancel");
        buttonCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonCancelActionPerformed(evt);
            }
        });

        buttonOK.setText("OK");
        buttonOK.setEnabled(false);
        buttonOK.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonOKActionPerformed(evt);
            }
        });

        buttonLoadOtherHID.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        buttonLoadOtherHID.setText("Load HID setup...");
        buttonLoadOtherHID.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonLoadOtherHIDActionPerformed(evt);
            }
        });

        buttonIdentifyNewHID.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        buttonIdentifyNewHID.setText("Start interactive setup now");
        buttonIdentifyNewHID.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonIdentifyNewHIDActionPerformed(evt);
            }
        });

        buttonSaveHidFile.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        buttonSaveHidFile.setText("Save HID setup...");
        buttonSaveHidFile.setEnabled(false);
        buttonSaveHidFile.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonSaveHidFileActionPerformed(evt);
            }
        });

        labelStatus.setText("Status:");

        labelDescription.setText("Description:");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(buttonLoadOtherHID)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(buttonSaveHidFile))
                    .add(layout.createSequentialGroup()
                        .add(buttonCancel)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(buttonOK))
                    .add(layout.createSequentialGroup()
                        .add(54, 54, 54)
                        .add(buttonIdentifyNewHID))
                    .add(layout.createSequentialGroup()
                        .add(10, 10, 10)
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(labelStatus, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 282, Short.MAX_VALUE)
                            .add(labelDescription, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 282, Short.MAX_VALUE))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                .add(79, 79, 79)
                .add(buttonIdentifyNewHID)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelDescription)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 80, Short.MAX_VALUE)
                .add(labelStatus)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(buttonLoadOtherHID)
                    .add(buttonSaveHidFile))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(buttonCancel)
                    .add(buttonOK))
                .add(8, 8, 8))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
        //Close

        //Return setup to how it was before -- not sure how I feel about this... But right now
        //we have to monopolize global setup in order for it to communicate via OSC. :(
        WekinatorInstance.getWekinatorInstance().setCurrentHidSetup(backup);
        /*    if (backup != null) {
        WekinatorInstance.getWekinatorInstance().setCurrentHidSetup(backup);
        } else {
        WekinatorInstance.getWekinatorInstance().setCurrentHidSetup(new HidSetup());
        } */
        this.dispose();
}//GEN-LAST:event_buttonCancelActionPerformed

    private void buttonOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOKActionPerformed
        //TODO: Check if currently has valid hid setup -- if so, kill it somehow?
        if (this.parent != null) {
            parent.setHidSetup(mySetup);
        }
        /* else {
        WekinatorInstance.getWekinatorInstance().setCurrentHidSetup(mySetup);
        } */
        this.dispose();
    }//GEN-LAST:event_buttonOKActionPerformed

    private void buttonLoadOtherHIDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonLoadOtherHIDActionPerformed
        boolean success = false;
        File file = Util.findLoadFile(HidSetup.getFileExtension(),
                HidSetup.getFileTypeDescription(),
                HidSetup.getDefaultLocation(),
                this);
        if (file == null)
            return;

        HidSetup loadedHs = null;
        try {
            loadedHs = HidSetup.readFromFile(file);
        } catch (FileNotFoundException ex) {
            System.out.println("Error: no such file found"); //todo; pop up box
            Logger.getLogger(HidSetupForm.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            System.out.println("Error: can't read HidSetup from this file");
            Logger.getLogger(HidSetupForm.class.getName()).log(Level.SEVERE, null, ex);
         }
        if (loadedHs != null) {
           try {
                setMyCurrentSetup(loadedHs);
                WekinatorInstance.getWekinatorInstance().setCurrentHidSetup(mySetup);
                // mySetup.startHidRun();
                // mySetup.startHidInit();
                 success = true;
                 Util.setLastFile(HidSetup.getFileExtension(), file);

                } catch (Exception ex) {
                    Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
                }
        }
        if (!success) {
            labelStatus.setText("Could not load settings successfully.");
            JOptionPane.showMessageDialog(this, "Could not load setup from file", "Could not load setup from file.", JOptionPane.ERROR_MESSAGE);
        }

}//GEN-LAST:event_buttonLoadOtherHIDActionPerformed

    private void buttonIdentifyNewHIDActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonIdentifyNewHIDActionPerformed
        if (!inInteractiveSetup) {
            try {
                // TODO: cancel any existing setup first?s
                WekinatorInstance.getWekinatorInstance().setCurrentHidSetup(mySetup);
                mySetup.requestHidSetup();
                setInInteractiveSetup(true);
                labelStatus.setText("Setup requested");
            } catch (IOException ex) {
                labelStatus.setText("Could not start setup");
                Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else {
            try {
                mySetup.requestSetupStop();
                labelStatus.setText("Status: Setup stopping");
            //displayHidSettings();
            } catch (IOException ex) {
                labelStatus.setText("Status: Encountered a problem.");
                System.out.println("setup stop exception");
                Logger.getLogger(MainGUI.class.getName()).log(Level.SEVERE, null, ex);
            }
            setInInteractiveSetup(false);
        }
}//GEN-LAST:event_buttonIdentifyNewHIDActionPerformed

    private void buttonSaveHidFileActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveHidFileActionPerformed
        File file = Util.findSaveFile(HidSetup.getFileExtension(),
                HidSetup.getFileTypeDescription(),
                HidSetup.getDefaultLocation(),
                this);
        if (file != null) {
            try {
                mySetup.writeToFile(file);
                Util.setLastFile(HidSetup.getFileExtension(), file);
            } catch (Exception ex) {
                Logger.getLogger(HidSetupForm.class.getName()).log(Level.INFO, null, ex);
                JOptionPane.showMessageDialog(this, ex.getMessage(), "Could not save setup to file.", JOptionPane.ERROR_MESSAGE);
            }
        }
}//GEN-LAST:event_buttonSaveHidFileActionPerformed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new HidSetupForm().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonCancel;
    private javax.swing.JButton buttonIdentifyNewHID;
    private javax.swing.JButton buttonLoadOtherHID;
    private javax.swing.JButton buttonOK;
    private javax.swing.JButton buttonSaveHidFile;
    private javax.swing.JLabel labelDescription;
    private javax.swing.JLabel labelStatus;
    // End of variables declaration//GEN-END:variables

    private File findHidSetupFile() {

        WekinatorInstance wek = WekinatorInstance.getWekinatorInstance();
        JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        String location = WekinatorInstance.getWekinatorInstance().getSettings().getLastKeyValue(HidSetup.getFileExtension());
        if (location == null || location.equals("")) {
            location = HidSetup.getDefaultLocation();
        }
        fc.setCurrentDirectory(new File(location)); //TODO: Could set directory vs file here according to above results

        boolean success = true;
        File file = null;
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            file = fc.getSelectedFile();
        }
        if (file != null) {
            wek.getSettings().setLastKeyValue(HidSetup.getFileExtension(), Util.getCanonicalPath(file));
        }
        return file;
    }

    private void setHidUsable(boolean usable) {
        buttonSaveHidFile.setEnabled(usable);
        buttonOK.setEnabled(usable);
    }

    //TODO TODO TODO: Add action listener whenever mysetup changes... 
    private void setupPropertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals(HidSetup.PROP_HIDSTATE)) {
            HidSetup.HidState state = mySetup.hidState;
            System.out.println("Received property change hid state: " + state);
            //  this.setInInteractiveSetup(state == HidState.SETUP_BEGUN);
            // buttonSaveHidFile.setEnabled(state == HidState.INIT_DONE || state== HidState.SETUP_STOPPED);

            if (state == HidState.INIT_DONE || state == HidState.SETTINGS_RECEIVED) {
                displayHidSettings();
            }

            //TODO: Make sure notduplicating effort here... 
            labelStatus.setText(mySetup.getStatusMessage());
        } else if (evt.getPropertyName().equals(HidSetup.PROP_USABLE)) {
            setHidUsable(mySetup.isUsable());
        }
    }

    private File findHidSetupFileToSave() {
        //TODO: Preopulate w/ reasonable thing.
        JFileChooser fc = new OverwritePromptingFileChooser();
        fc.setDialogType(JFileChooser.SAVE_DIALOG);
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);

        String location = WekinatorInstance.getWekinatorInstance().getSettings().getLastKeyValue(HidSetup.getFileExtension());
        if (location == null || location.equals("")) {
            location = HidSetup.getDefaultLocation();
        }
        fc.setCurrentDirectory(new File(location)); //TODO: Could set directory vs file here according to above results

        File file = null;

        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {

            file = fc.getSelectedFile();
        }
        if (file != null) {
            WekinatorInstance.getWekinatorInstance().getSettings().setLastKeyValue(HidSetup.getFileExtension(), Util.getCanonicalPath(file));
        }
        return file;
    }

    private void setInInteractiveSetup(boolean inSetup) {
        if (inSetup) {
            buttonIdentifyNewHID.setText("End interactive setup");
        } else {
            buttonIdentifyNewHID.setText("Begin interactive setup");
        }
        inInteractiveSetup = inSetup;
    }

    private void displayHidSettings() {
        String s = mySetup.getDescription();
        labelDescription.setText(s);
    }
}
